﻿using System;
using System.Text.RegularExpressions;

namespace airwolf.SSDP
{
    public enum SSDPMessageTypes
    {
        OK,
        Notify,
        Search,
        Unknown,
    }

    public class SSDPMessage
    {
        private readonly SSDPMessageTypes _type = SSDPMessageTypes.Unknown;
        public const string SearchHeader = "M-SEARCH * HTTP/1.1";
        public const string NotifyHeader = "NOTIFY * HTTP/1.1";
        public const string OKHeader = "HTTP/1.1 200 OK";
        public readonly string HostIP;
        public readonly int HostPort;
        public readonly string Schema;

        private const string NotifyFormat =
            "NOTIFY * HTTP/1.1\r\n" +
            "HOST: {0}\r\n" +
            "NT: {1}\r\n" +
            "NTS: {6}\r\n" +
            "LOCATION: {2}\r\n" +
            "USN: {3}\r\n" +
            "CACHE-CONTROL: {4}\r\n" +
            "SERVER: {5}\r\n\r\n";

        private static readonly Regex _searchRe = new Regex(String.Format(@"^{0}\r\nHOST\:\s*(?<ip>[\d\.]+)\:(?<port>\d+)\r\nST\:\s*(?<schema>[^\r\n]+)\r\nMAN\:\s*[^\r\n]+\r\nMX\:\s*[^\r\n]+\r\n", Regex.Escape(SearchHeader)), RegexOptions.IgnoreCase);
        private static readonly Regex _notifyRe = new Regex(@"^NOTIFY \* HTTP/1\.1\r\n");//String.Format(NotifyFormat, @"(?<host>[^\:\r]+)(\:(?<port>\d+))?", @"(?<schema>[^\r]+)", "[^\r]+", "[^\r]+", "[^\r]+", "[^\r]+", "[^\r]+"));

        private SSDPMessage()
        { 
        }

        private SSDPMessage(SSDPMessageTypes Type, string HostIP, int HostPort, string Schema)
        {
            _type = Type;
            this.HostIP = HostIP;
            this.HostPort = HostPort;
            this.Schema = Schema;
        }

        public static string CreateOK(string USN, string Schema, string ServiceURL)
        {
            return String.Format(
                "HTTP/1.1 200 OK\r\n"+
                "ST:{0}\r\n"+
                "USN:{1}\r\n"+
                "Location:{2}\r\n"+
                "OPT:\"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n"+
                "01-NLS:53b030c6e681204731989c2285d6fd0a\r\n"+
                "Cache-Control:max-age=900\r\n"+
                "Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0\r\n"+
                "Ext:\r\n\r\n", Schema, USN, ServiceURL);
        }

        public static bool TryParse(string Text, out SSDPMessage Search)
        {
            Search = new SSDPMessage();

            Match m = _searchRe.Match(Text);

            if (m.Success)
            {
                Search = new SSDPMessage(SSDPMessageTypes.Search, m.Groups["ip"].Value, Int32.Parse(m.Groups["port"].Value), m.Groups["schema"].Value);
                return true;
            }
            else if ((m = _notifyRe.Match(Text)).Success)
            {
                Search = new SSDPMessage(SSDPMessageTypes.Notify, m.Groups["host"].Value, 0, m.Groups["schema"].Value);
                return true;
            }
            return false;
        }

        public SSDPMessageTypes Type
        {
            get
            {
                return _type;
            }
        }
    }
}
/*
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
ST: urn:schemas-upnp-org:device:MediaServer:1
MAN: "ssdp:discover"
MX: 2
X-AV-Client-Info: av=5.0; cn="Sony Computer Entertainment Inc."; mn="PLAYSTATION 3"; mv="1.0";


HTTP/1.1 200 OK
ST:urn:schemas-upnp-org:device:MediaServer:1
USN:uuid:0af6e9d9-7e49-48d3-bfd4-18d0a1b56d42::urn:schemas-upnp-org:device:MediaServer:1
Location:http://192.168.1.104:2869/upnphost/udhisapi.dll?content=uuid:0af6e9d9-7e49-48d3-bfd4-18d0a1b56d42
OPT:"http://schemas.upnp.org/upnp/1/0/"; ns=01
01-NLS:53b030c6e681204731989c2285d6fd0a
Cache-Control:max-age=900
Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0
Ext:
 */